package com.yao.spider.proxy.task;

import com.yao.spider.core.util.Config;
import com.yao.spider.core.util.Constants;
import com.yao.spider.proxy.ProxyHttpClient;
import com.yao.spider.proxy.entity.Direct;
import com.yao.spider.proxy.entity.Proxy;
import com.yao.spider.proxy.site.ProxyListPageParaserFactory;
import com.yao.spider.core.util.HttpClientUtil;
import com.yao.spider.proxy.ProxyListPageParser;
import com.yao.spider.proxy.ProxyPool;
import com.yao.spider.zhihu.Page;
import com.yao.spider.zhihu.ZhiHuHttpClient;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.HttpHost;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.List;

/**
 * Created by 单耀 on 2017/12/6.
 * 下载代理网页并解析
 * 如果下载失败则使用代理下载
 */
public class ProxyPageTask implements Runnable{
    private static final Logger logger = LoggerFactory.getLogger(ProxyPageTask.class);
    protected String url;
    private boolean proxyFlag;//是否通过代理下载
    private Proxy currentProxy;//当前线程使用的代理

    protected static ProxyHttpClient proxyHttpClient = ProxyHttpClient.getInstance();

    private ProxyPageTask(){

    }
    public ProxyPageTask(String url, boolean proxyFlag){
        this.url = url;
        this.proxyFlag = proxyFlag;
    }

    public void run() {
        long requestStartTime = System.currentTimeMillis();
        HttpGet tempRequest = null;
        try {
            Page page = null;
            if (proxyFlag) {
                tempRequest = new HttpGet(url);

                currentProxy = ProxyPool.proxyQueue.take();

                //TODO 这儿要理解一下
                if (!(currentProxy instanceof Direct)){
                    HttpHost proxy = new HttpHost(currentProxy.getIp(),currentProxy.getPort());
                    tempRequest.setConfig(HttpClientUtil.getRequestConfigBuilder().setProxy(proxy).build());
                }
                page = proxyHttpClient.getWebPage(tempRequest);
            } else {
                page =  proxyHttpClient.getWebPage(url);
            }
            page.setProxy(currentProxy);
            int status = page.getStatusCode();
            long requestEndTime =  System.currentTimeMillis();
            String logStr = Thread.currentThread().getName() + " " + getProxyStr(currentProxy) +
                    " executing request " + page.getUrl() + " response statusCode:" + status +
                    " request cost time:" + (requestEndTime - requestStartTime) + "ms";
                if (status == HttpStatus.SC_OK) {
                    logger.debug(logStr);
                    //处理页面
                    handle(page);
                } else {
                    logger.error(this.getClass().getSimpleName()+":请求返回错误代码："+logStr);
                    Thread.sleep(100);
                    retry();
                }

        }catch (InterruptedException e) {
            logger.error("InterruptedException", e);
        } catch (IOException e) {
            retry();
//            logger.error("InterruptedException", e);
        } finally {
            if (currentProxy != null) {
                currentProxy.setTimeIntervsl(Constants.TIME_INTERVAL);
                ProxyPool.proxyQueue.add(currentProxy);
            }

            if (tempRequest != null) {
                tempRequest.releaseConnection();
            }
        }

    }

    public void retry() {
        //再次尝试使用代理
        proxyHttpClient.getProxyDownLoadThreadExecutor().execute(new ProxyPageTask(url, Config.isProxy));
    }

    //处理下载页面
    public void handle(Page page) {
        if (page.getHtml() == null || page.getHtml().equals("")) {
            return;
        }

        //TODO 下面处理详细代码
        ProxyListPageParser parser = ProxyListPageParaserFactory.getProxyListPageParser(ProxyPool.proxyMap.get(url));
        List<Proxy> proxyList = parser.parse(page.getHtml());
        for (Proxy p : proxyList) {
            //isTerminated判断是否为关闭状态，是返回true，否返回false
            if (!ZhiHuHttpClient.getInstance().getDetailListPageThreadPool().isTerminated()) {
                //读写锁
                ProxyPool.lock.readLock().lock();
                boolean containFlag = ProxyPool.proxySet.contains(p);
                ProxyPool.lock.readLock().unlock();

                if (!containFlag) {
                    ProxyPool.lock.writeLock().lock();
                    ProxyPool.proxySet.add(p);
                    ProxyPool.lock.writeLock().unlock();

                    //启动测试代理线程池
                    proxyHttpClient.getProxyTestThreadExector().execute(new ProxyTestTask(p));
                }
            }

        }
    }

    private String getProxyStr(Proxy proxy) {
        if (proxy == null)
            return "";

        return proxy.getIp() + ":" + proxy.getPort();
    }
}
